#include "BaseType.h"
#include "Tracer.h"
#include "StrUtil.h"

using namespace std;
using namespace libemb;

/**
 * 设计模式：
 * 1.定义语言的文法,并且建立一个解释器来解释该语言中的句子
 * 2.解释器模式中使用了递归,执行效率低
 * 3.可利用场景少,一般应用在较简单的语法解释器中(如数据库语法解析) 
 * 适用场景：
 * 1.将需要解释执行的语言表述为抽象语法树
 * 2.可扩展新表达式，但容易出现类爆炸
 **/
class Context;

//抽象表达式
class Expression{
DECL_CLASSNAME(Expression)
public:
    virtual int interprete(Context& ctx)=0;
};

//终结符表达式
class ValueExpression:public Expression{
DECL_CLASSNAME(ValueExpression)
private:
    int m_value{0};
public:
    ValueExpression(std::string value)
    {
        m_value = StrUtil::stringToInt(value);
    }
    int interprete(Context& ctx) override
    {
        return m_value;
    }
};

//非终结符表达式
class SymbolExpression:public Expression{
DECL_CLASSNAME(SymbolExpression)
protected:
    Expression* m_leftExp;
    Expression* m_rightExp;
public:
    SymbolExpression(Expression* left, Expression* right)
    {
        m_leftExp = left;
        m_rightExp = right;
    }
    int interprete(Context& ctx) override
    {
        return 0;
    }
};

class AddExpression:public SymbolExpression{
DECL_CLASSNAME(AddExpression)
public:
    AddExpression(Expression* left, Expression* right):SymbolExpression(left,right){};
    int interprete(Context& ctx) override
    {
        return m_leftExp->interprete(ctx)+m_rightExp->interprete(ctx);
    }
};

class SubExpression:public SymbolExpression{
DECL_CLASSNAME(SubExpression)
public:
    SubExpression(Expression* left, Expression* right):SymbolExpression(left,right){};
    int interprete(Context& ctx) override
    {
        return m_leftExp->interprete(ctx)-m_rightExp->interprete(ctx);
    }
};


//上下文
class Context{
DECL_CLASSNAME(Context)
private:
    std::vector<Expression*> m_stack;
    Expression* m_result;
public:
    Context(std::string statement)
    {
        auto exps = StrUtil::splitString(statement," ");
        for(auto i=0; i<exps.size(); i++)
        {
            if (exps[i]=="+")
            {
                auto left = m_stack.back();
                m_stack.pop_back();

                auto right = new ValueExpression(exps[++i]);
                auto exp = new AddExpression(left,right);
                m_stack.push_back(exp);
            }
            else if (exps[i]=="-")
            {
                auto left = m_stack.back();
                m_stack.pop_back();

                auto right = new ValueExpression(exps[++i]);
                auto exp = new SubExpression(left,right);
                m_stack.push_back(exp);
            }
            else
            {
                auto vexp = new ValueExpression(exps[i]);
                m_stack.push_back(vexp);
            }
        }
        m_result = m_stack.back();
        m_stack.pop_back();
    }
    int compute(Context& ctx)
    {
        return m_result->interprete(ctx);
    }
};


int main()
{
    Tracer::getInstance().setLevel(TRACE_LEVEL_DBG);
	Tracer::getInstance().addSink(std::make_shared<STDSink>());

    Context context("3 + 4 - 2");
    TRACE_INFO("3+4-2=%d",context.compute(context));
    return RC_OK;
}